package cn.nbt.busManage.service.impl;

import cn.nbt.busManage.dao.mapper.RouteMapper;
import cn.nbt.busManage.model.dto.PointDto;
import cn.nbt.busManage.model.dto.RouteDto;
import cn.nbt.busManage.model.entity.Point;
import cn.nbt.busManage.model.entity.Route;
import cn.nbt.busManage.dao.repository.RouteRepository;
import cn.nbt.busManage.service.PointService;
import cn.nbt.busManage.service.RouteService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

/**
 * {@code @Author} lyq
 * {@code @Date} 6/13/2024 7:16 PM
 */

@Service
@Transactional
public class IRouteService implements RouteService {

    @Autowired
    private RouteRepository routeRepository;

    @Autowired
    private PointService pointService;

    @Autowired
    private RouteMapper routeMapper;

    /**
     * 查询所有线路
     * @return 线路信息
     */
    public List<RouteDto> findAllRoute() {
        List<Route> routes = routeRepository.findAll();
        return getRouteDtos(routes);
    }

    /**
     * 添加线路
     * @param routeDto 线路信息
     */
    @Override
    public void addRoute(RouteDto routeDto) {
        Route route = new Route();
        route.setRouteName(routeDto.getRouteName());
        route.setStartPointId(routeDto.getStartPointId());
        route.setEndPointId(routeDto.getEndPointId());
        route.setPoints(routeDto.getPoints());
        route.setTimes(routeDto.getTimes());
        routeRepository.save(route);
    }

    /**
     * 更新线路
     * @param routeDto 线路信息
     */
    @Override
    public void updateRoute(RouteDto routeDto) {
        Integer id = routeDto.getId();
        Route route = routeRepository.findById(id).orElse(null);
        if(route == null) throw new RuntimeException("线路不存在");
        if(!route.getRouteName().equals(routeDto.getRouteName())){
            routeRepository.findByRouteName(routeDto.getRouteName()).ifPresent(r -> {
                throw new RuntimeException("线路已存在");
            });
        }
        Route route1 = new Route();
        route1.setId(routeDto.getId());
        route1.setRouteName(routeDto.getRouteName());
        route1.setStartPointId(routeDto.getStartPointId());
        route1.setEndPointId(routeDto.getEndPointId());
        route1.setPoints(routeDto.getPoints());
        route1.setTimes(routeDto.getTimes());
        routeRepository.updateRoute(route1.getId(), route1.getRouteName(), route1.getStartPointId(), route1.getEndPointId(), route1.getPoints(), route1.getTimes());

    }

    /**
     * 删除线路
     * @param routeId 线路id
     */
    @Override
    public void deleteRoute(Integer routeId) {
        routeRepository.deleteById(routeId);
    }

    /**
     * 根据站点名称查询线路
     * @param pointName 站点名称
     * @return 线路信息
     */
    @Override
    public List<RouteDto> findRouteByPointName(String pointName) {
        Point point = pointService.findByPointName(pointName);
        if(point == null) return null;
        List<Route> routes = findByPointId(point.getId());
        return getRouteDtos(routes);
    }

    /**
     * 根据线路名称查询线路
     * @param voRouteName 线路名称
     * @return 线路信息
     */
    @Override
    public boolean findRouteByName(String voRouteName) {
        Route route = routeRepository.findByRouteName(voRouteName).orElse(null);
        return route != null;
    }

    /**
     * 根据id查询线路
     * @param id 线路id
     */
    @Override
    public RouteDto findById(Integer id) {
        Optional<Route> route = routeRepository.findById(id);
        return routeToRouteDto(route.get());
    }

    /**
     * 获取RouteDto
     * @param route 线路信息
     * @return RouteDto
     */
    private RouteDto routeToRouteDto(Route route){
        if (route == null) return null;
        RouteDto routeDto = new RouteDto(route);
        PointDto startPoint = pointService.findById(routeDto.getStartPointId());
        PointDto endPoint = pointService.findById(routeDto.getEndPointId());
        if(startPoint == null || endPoint == null) return null;
        routeDto.setStartToEndPoint(startPoint.getPointName() + "-" + endPoint.getPointName());
        String[] points = routeDto.getPoints().split(",");
        List<PointDto> pointDtos = new ArrayList<>();
        for (String point : points) {
            PointDto pointDto = pointService.findById(Integer.parseInt(point));
            if (pointDto == null) continue;
            pointDtos.add(pointDto);
        }
        routeDto.setPointDtos(pointDtos);
        String[] times = routeDto.getTimes().split(",");
        List<Map<List<PointDto>, String>> pointsTime = new ArrayList<>();
        int sumTime = 0;
        for (int i = 0; i < points.length - 1; i++) {
            Map<List<PointDto>, String> map = Map.of(List.of(pointDtos.get(i), pointDtos.get(i + 1)), times[i]);
            pointsTime.add(map);
            sumTime += Integer.parseInt(times[i]);
        }
        routeDto.setPointsTime(pointsTime);
        routeDto.setSumTime(sumTime);
        return routeDto;
    }

    @Transactional("mybatisTransactionManager")
    public List<Route> findByPointId(Integer PointId) {
        return routeMapper.findByPoindId(PointId);
    }

    /**
     * 获取RouteDto
     * @param routes 线路信息
     * @return RouteDto
     */
    private List<RouteDto> getRouteDtos(List<Route> routes) {
        if(routes.isEmpty()) return null;
        List<RouteDto> routeDtos = new ArrayList<>();
        for (Route route : routes) {
            RouteDto routeDto = new RouteDto(route);
            PointDto startPoint = pointService.findById(route.getStartPointId());
            PointDto endPoint = pointService.findById(route.getEndPointId());
            if(startPoint == null || endPoint == null) continue;
            String pointStartName = startPoint.getPointName();
            String pointEndName = endPoint.getPointName();
            routeDto.setStartToEndPoint(pointStartName + "-" + pointEndName);
            if(route.getPoints() == null || route.getTimes() == null) continue;
            String[] points = route.getPoints().split(",");
            List<PointDto> pointDtos = new ArrayList<>();
            for (String point : points) {
                PointDto pointDto = pointService.findById(Integer.parseInt(point));
                if (pointDto == null) continue;
                pointDtos.add(pointDto);
            }
            routeDto.setPointDtos(pointDtos);
            String[] times = route.getTimes().split(",");
            List<Map<List<PointDto>, String>> pointsTime = new ArrayList<>();
            int sumTime = 0;
            for (int i = 0; i < points.length - 1; i++) {
                Map<List<PointDto>, String> map = Map.of(List.of(pointDtos.get(i), pointDtos.get(i + 1)), times[i]);
                pointsTime.add(map);
                sumTime += Integer.parseInt(times[i]);
            }
            routeDto.setPointsTime(pointsTime);
            routeDto.setSumTime(sumTime);
            routeDtos.add(routeDto);
        }
        return routeDtos;
    }
}
